/* Archive Extractor
 * Copyright 2008-2009 Matthew Hoops
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 *
 * $URL: http://archive-extractor.googlecode.com/svn/trunk/bzip2.cpp $
 * $Id: bzip2.cpp 2 2009-03-23 01:29:43Z clone2727 $
 *
 */

#include "bzip2.h"

BZip2Archive::BZip2Archive() : Archive() {
}

std::vector<const char*> BZip2Archive::getArchiveExtensions() {
	std::vector<const char*> exList;
	exList.push_back("bz2");
	exList.push_back("tbz2"); // This is a tarball (really tar.bz2)
	return exList;
}

int BZip2Archive::detect(const char* filename) {
	static const byte bzip2Header[] = { 'B', 'Z', 'h', '9', '1' };
	
	// First, let's do our own check of the header.
	FILE* file = fopen(filename, "rb");
	for (byte i = 0; i < 5; i++)
		if (readByte(file) != bzip2Header[i]) {
			fclose(file);
			return 0;
		}
	
	// Reset back to the start
	fseek(file, 0, SEEK_SET);
	
	// Let's run it through the file opener now
	int bzError;
	_handle = BZ2_bzReadOpen(&bzError, file, 0, 0, NULL, 0);
	
	if (bzError != BZ_OK) {
		fclose(file);
		return 0;
	}

	return 100;
}

// Read data in chunks of 16384 bytes at a time
#define BZIP2_CHUNK_SIZE 16384

bool BZip2Archive::extractFiles(const char* filename) {
	const char* outputFileName = genOutFileName(filename);
	printf ("Extracting file \'%s\'...\n", outputFileName);
	
	FILE* output = fopen(outputFileName, "wb");
	
	int result = BZ_OK;
	
	while (result != BZ_STREAM_END) {
		byte *data = (byte *)malloc(BZIP2_CHUNK_SIZE);
		uint32 actualSize = BZ2_bzRead(&result, _handle, data, BZIP2_CHUNK_SIZE);
		if (result != BZ_STREAM_END && result != BZ_OK) {
			free(data);
			BZ2_bzReadClose(&result, _handle);
			fclose(output);
			return false;
		}
		fwrite(data, 1, actualSize, output);
		free(data);
	}
	
	fflush(output);
	fclose(output);
	
	BZ2_bzReadClose(&result, _handle);
	
	return (result == BZ_OK);
}

const char* BZip2Archive::genOutFileName(const char* filename) {
	return "bzip2_temp.tar"; // TODO
}
